package com.wanger.swc.config.myBatisPlus;

import cn.hutool.core.date.DateUtil;
import com.wanger.swc.config.myBatisPlus.autoDDL.AutoDDLDispatcher;
import com.wanger.swc.config.myBatisPlus.autoDDL.AutoDDLService;
import com.wanger.swc.config.myBatisPlus.autoDDL.AutoDDlConfig;
import com.wanger.swc.config.myBatisPlus.autoDDL.model.MyDBType;
import com.wanger.swc.exception.BusEx;
import com.wanger.swc.util.validation.MyVerifyUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.anyline.metadata.type.DatabaseType;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.context.ApplicationContext;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import java.util.Collection;
import java.util.HashMap;
import java.util.Map;

/**
 * @Author: wanger
 * @Date: 2025/1/17 14:48
 * @Description:
 */
@Slf4j
@Component
@RequiredArgsConstructor
@Order(Ordered.HIGHEST_PRECEDENCE)//最高优先级
public class MybatisPlusStartupRunner implements ApplicationRunner {

    private final AutoDDlConfig config;
    private final AutoDDLDispatcher autoDDLDispatcher;
    private final ApplicationContext applicationContext;

    /**
     * mybatis-plus启动时回调
     *
     * @param args 启动参数
     */
    @Override
    public void run(ApplicationArguments args) {
        log.info("启动mybatis-plus立即执行任务！");
        long l = System.currentTimeMillis();
        //1.验证配置的sql是否合法
        validityVerification();
        log.info("所有配置的sql返回字段验证完成，用时【{}】！", DateUtil.formatBetween(System.currentTimeMillis() - l));
        l = System.currentTimeMillis();
        if (config.isEnabled()) {
            //2.直接调用mybatis-plus立即执行任务
            autoDDLDispatcher.start();
        }
        log.info("mybatis-plus立即执行任务执行完成！用时【{}】！", DateUtil.formatBetween(System.currentTimeMillis() - l));
    }

    /**
     * 1.验证配置的getContentType不能为空；<br>
     * 2.验证getFieldMappers()字段映射不能为空；<br>
     * 3.验证getContentType不能重复配置；<br>
     * 4.循环验证sql是否合法<br>
     */
    private void validityVerification() {
        Collection<AutoDDLService> values = applicationContext.getBeansOfType(AutoDDLService.class).values();
        Map<DatabaseType, AutoDDLService> map = new HashMap<>();
        for (AutoDDLService value : values) {
            MyVerifyUtil.nullVerify(value::getFieldMappers, "【{}】类实现的getFieldMappers()不能为空！", value.getClass().getName());
            MyDBType dbType = MyVerifyUtil.nullVerify(value::getContentType, "【{}】类实现的getContentType()不能为空！", value.getClass().getName());
            DatabaseType type = MyVerifyUtil.nullVerify(dbType::getDbType);
            if (map.get(type) != null) {
                BusEx.throwEx("在【{}】类与【{}】类的getContentType()配置存在重复！", map.get(type).getClass().getName(), value.getClass().getName());
            } else map.put(type, value);
        }
    }
}
